package com.wondertek.common.util.base;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.api.UserApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.*;
import com.getui.push.v2.sdk.dto.req.message.PushBatchDTO;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.ios.Alert;
import com.getui.push.v2.sdk.dto.req.message.ios.Aps;
import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO;
import com.getui.push.v2.sdk.dto.res.AliasResDTO;
import com.getui.push.v2.sdk.dto.res.QueryCidResDTO;
import com.getui.push.v2.sdk.dto.res.TaskIdDTO;
import com.google.common.collect.Lists;
import com.wondertek.common.exception.AppException;
import com.wondertek.common.util.getui.PushDto;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * @author: gongjiangtao
 * @date: 2024/8/26 17:03
 * @Description: 推送工具类
 * @Version: 1.0
 */
@Slf4j
@Component
public class PushUtil {

    @Resource
    private PushApi pushApi;

    @Resource
    private UserApi userApi;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    private final static String PUSH_TASK_ID = "push:taskid:";


    /**
     * 设置公共推送参数
     *
     * @return
     */
    private PushDTO<Audience> setCommonPushParam(PushDto pushDto) {
        PushDTO<Audience> pushDTO = new PushDTO<>();
        pushDTO.setRequestId(IdUtil.fastSimpleUUID());
        Settings settings = new Settings();
        settings.setTtl(7200000);
        // 厂商下发策略
        Strategy strategy = new Strategy();
        strategy.setDef(1);
        settings.setStrategy(strategy);
        pushDTO.setSettings(settings);

        Audience audience = new Audience();
        // 设备标志不为空时，设置
        if (StrUtil.isNotBlank(pushDto.getCId())) {
            audience.setCid(List.of(pushDto.getCId()));
        }
        if (StrUtil.isNotBlank(pushDto.getAlias())) {
            audience.setAlias(List.of(pushDto.getAlias()));
        }
        pushDTO.setAudience(audience);


        PushMessage pushMessage = new PushMessage();
        GTNotification gtNotification = new GTNotification();
        gtNotification.setTitle(pushDto.getTitle());
        gtNotification.setBody(pushDto.getContent());
        gtNotification.setClickType("intent");
        gtNotification.setIntent("intent://io.dcloud.unipush/?#Intent;scheme=unipush;launchFlags=0x4000000;component=uni.UNI07AD05F/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.payload=/pages/notices/notices;end");
        pushMessage.setNotification(gtNotification);
        pushDTO.setPushMessage(pushMessage);

        // 厂商通道
        PushChannel pushChannel = new PushChannel();
        AndroidDTO androidDTO = new AndroidDTO();
        Ups ups = new Ups();
        ThirdNotification thirdNotification = new ThirdNotification();
        thirdNotification.setTitle(pushDto.getTitle());
        thirdNotification.setBody(pushDto.getContent());
        thirdNotification.setClickType("intent");
        thirdNotification.setIntent("intent://io.dcloud.unipush/?#Intent;scheme=unipush;launchFlags=0x4000000;component=uni.UNI07AD05F/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.payload=/pages/notices/notices;end");
        ups.setNotification(thirdNotification);
        androidDTO.setUps(ups);
        pushChannel.setAndroid(androidDTO);

        IosDTO iosDTO = new IosDTO();
        Aps aps = new Aps();
        Alert alert = new Alert();
        alert.setTitle(pushDto.getTitle());
        alert.setBody(pushDto.getContent());
        aps.setAlert(alert);
        iosDTO.setAps(aps);
        // voip：voip语音推送，notify：apns通知消息，liveactivity：灵动岛推送(不支持p12证书)
        iosDTO.setType("notify");
        // 用于计算icon上显示的数字，还可以实现显示数字的自动增减，如“+1”、 “-1”、 “1” 等，计算结果将覆盖badge
        iosDTO.setAutoBadge("+1");
        // ios todo 自定义消息？？？
        iosDTO.setPayload("自定义消息");
        pushChannel.setIos(iosDTO);
        pushDTO.setPushChannel(pushChannel);
        return pushDTO;
    }

    /**
     * 推送参数设置
     *
     * @param list
     * @return
     */
    private List<PushDTO<Audience>> setPushDTO(List<PushDto> list) {
        List<PushDTO<Audience>> pushDTOList = Lists.newArrayList();
        for (PushDto pushDto : list) {
            pushDTOList.add(setCommonPushParam(pushDto));
        }
        return pushDTOList;
    }


    /**
     * cid单推
     *
     * @param cid
     * @param title   通知消息标题，长度 ≤ 50字
     * @param content 通知消息内容，长度 ≤ 256字
     */
    public void pushToSingleByCid(String cid, String title, String content) {
        List<PushDto> list = Lists.newArrayList();
        PushDto pushDto = new PushDto();
        pushDto.setCId(cid);
        pushDto.setTitle(title);
        pushDto.setContent(content);
        list.add(pushDto);
        List<PushDTO<Audience>> pushDTO = setPushDTO(list);
        ApiResult<Map<String, Map<String, String>>> result = pushApi.pushToSingleByCid(pushDTO.getFirst());
        if (result.isSuccess()) {
            log.info("推送成功");
            log.info("推送结果: {}", JSONUtil.toJsonStr(result.getData()));
        } else {
            log.error("推送失败: {}", JSONUtil.toJsonStr(result));
        }
    }

    /**
     * 别名单推
     *
     * @param alias   别名
     * @param title   通知消息标题，长度 ≤ 50字
     * @param content 通知消息内容，长度 ≤ 256字
     */
    public void pushToSingleByAlias(String alias, String title, String content) {
        List<PushDto> list = Lists.newArrayList();
        PushDto pushDto = new PushDto();
        pushDto.setAlias(alias);
        pushDto.setTitle(title);
        pushDto.setContent(content);
        list.add(pushDto);
        List<PushDTO<Audience>> pushDTO = setPushDTO(list);
        ApiResult<Map<String, Map<String, String>>> result = pushApi.pushToSingleByAlias(pushDTO.getFirst());
        if (result.isSuccess()) {
            log.info("推送成功");
            log.info("推送结果: {}", JSONUtil.toJsonStr(result.getData()));
        } else {
            log.error("推送失败: {}", JSONUtil.toJsonStr(result));
        }
    }

    /**
     * cid批量单推 设置cid字段的值
     *
     * @param async 是否异步推送，true是异步，false同步。异步推送不会返回data详情
     * @param list  消息内容，数组长度不大于 200
     */
    public void pushBatchByCid(boolean async, List<PushDto> list) {
        PushBatchDTO pushBatchDTO = new PushBatchDTO();
        // 是否异步
        pushBatchDTO.setAsync(async);
        List<PushDTO<Audience>> pushDTO = setPushDTO(list);
        pushBatchDTO.setMsgList(pushDTO);
        ApiResult<Map<String, Map<String, String>>> result = pushApi.pushBatchByCid(pushBatchDTO);
        if (!async) {
            if (result.isSuccess()) {
                log.info("推送成功");
            } else {
                log.error("推送失败: {}", JSONUtil.toJsonStr(result));
            }
        }
    }

    /**
     * 别名批量单推 设置alias字段的值
     *
     * @param async 是否异步推送，true是异步，false同步。异步推送不会返回data详情
     * @param list  消息内容，数组长度不大于 200
     */
    public void pushBatchByAlias(boolean async, List<PushDto> list) {
        PushBatchDTO pushBatchDTO = new PushBatchDTO();
        // 是否异步
        pushBatchDTO.setAsync(async);
        List<PushDTO<Audience>> pushDTO = setPushDTO(list);
        pushBatchDTO.setMsgList(pushDTO);
        ApiResult<Map<String, Map<String, String>>> result = pushApi.pushBatchByAlias(pushBatchDTO);
        if (!async) {
            if (result.isSuccess()) {
                log.info("推送成功");
            } else {
                log.error("推送失败: {}", JSONUtil.toJsonStr(result));
            }
        }
    }

    /**
     * 创建消息
     *
     * @param title
     * @param content
     * @return taskid  任务编号，用于执行cid批量推和执行别名批量推，此taskid可以多次使用，有效期为用户设置的离线时间
     */
    public String createMsg(String title, String content) {
        PushDto pushDto = new PushDto();
        pushDto.setTitle(title);
        pushDto.setContent(content);
        PushDTO<Audience> pushDTO = setCommonPushParam(pushDto);
        ApiResult<TaskIdDTO> result = pushApi.createMsg(pushDTO);
        if (result.isSuccess()) {
            String taskid = result.getData().getTaskId();
            log.info("创建消息成功");
            log.info("创建消息结果: {}", JSONUtil.toJsonStr(result.getData()));
            return result.getData().getTaskId();
        } else {
            log.error("创建消息失败: {}", JSONUtil.toJsonStr(result));
            return null;
        }
    }

    private String generateCacheKey(String title, String content) {
        // 生成缓存键，确保唯一性
        return PUSH_TASK_ID + SecureUtil.md5(title + content);
    }


    /**
     * 绑定别名
     * 一个别名最多允许绑定10个cid
     * 数据列表，数组长度不大于1000
     *
     * @param list 字母（区分大小写）、数字、下划线、汉字; 长度<40字;
     */
    public void bindAlias(List<CidAliasListDTO.CidAlias> list) {
        CidAliasListDTO cidAliasListDTO = new CidAliasListDTO();
        cidAliasListDTO.setDataList(list);
        ApiResult<Void> result = userApi.bindAlias(cidAliasListDTO);
        if (result.isSuccess()) {
            log.info("绑定成功");
        } else {
            log.error("绑定失败: {}", JSONUtil.toJsonStr(result));
        }
    }


    /**
     * 根据cid查询别名
     *
     * @param cid
     */
    public String queryAliasByCid(String cid) {
        ApiResult<AliasResDTO> result = userApi.queryAliasByCid(cid);
        if (result.isSuccess()) {
            log.info("查询成功");
            return result.getData().getAlias();
        } else {
            log.error("查询失败: {}", JSONUtil.toJsonStr(result));
        }
        return null;
    }

    /**
     * 根据别名查询cid
     *
     * @param alias
     */
    public List<String> queryCidByAlias(String alias) {
        ApiResult<QueryCidResDTO> result = userApi.queryCidByAlias(alias);
        if (result.isSuccess()) {
            log.info("查询成功");
            return result.getData().getCid();
        } else {
            log.error("查询失败: {}", JSONUtil.toJsonStr(result));
        }
        return null;
    }


    /**
     * 执行cid批量推
     * 同一个taskid,发送给相同的cid,只会成功一次
     *
     * @param cidList cid数组，数组长度不大于1000
     * @param title   标题
     * @param content 内容
     * @param async   是否异步推送，true是异步，false同步。异步推送不会返回data详情
     */
    public void pushListByCid(List<String> cidList, String title, String content, boolean async) {
//        String cacheKey = generateCacheKey(title, content);
//        String taskid = redisTemplate.opsForValue().get(cacheKey);
//        if (StrUtil.isBlank(taskid)) {
//            taskid = createMsg(title, content);
//            if (StrUtil.isBlank(taskid)) {
//                throw new AppException("创建消息失败!");
//            }
//            // 将新创建的taskid存入缓存，设置过期时间为ttl
//            redisTemplate.opsForValue().set(cacheKey, taskid, 7200000, TimeUnit.MILLISECONDS); // 假设ttl为7200秒
//        }
        String taskid = createMsg(title, content);
        if (StrUtil.isBlank(taskid)) {
            throw new AppException("创建消息失败!");
        }
        log.info("taskid: {}", taskid);
        AudienceDTO audienceDTO = new AudienceDTO();
        audienceDTO.setTaskid(taskid);
        Audience audience = new Audience();
        audience.setCid(cidList);
        audienceDTO.setAudience(audience);
        audienceDTO.setAsync(async);
        ApiResult<Map<String, Map<String, String>>> result = pushApi.pushListByCid(audienceDTO);
        if (!async) {
            if (result.isSuccess()) {
                log.info("推送成功");
                log.info("推送结果: {}", JSONUtil.toJsonStr(result.getData()));
            } else {
                log.error("推送失败: {}", JSONUtil.toJsonStr(result));
            }
        }
    }


    /**
     * 执行别名批量推
     * 同一个taskid,发送给相同的cid,只会成功一次
     *
     * @param aliasList alias数组，数组长度不大于1000
     * @param title     标题
     * @param content   内容
     * @param async     是否异步推送，true是异步，false同步。异步推送不会返回data详情
     */
    public void pushListByAlias(List<String> aliasList, String title, String content, boolean async) {
        String taskid = createMsg(title, content);
        if (StrUtil.isBlank(taskid)) {
            throw new AppException("创建消息失败!");
        }
        log.info("taskid: {}", taskid);
        AudienceDTO audienceDTO = new AudienceDTO();
        audienceDTO.setTaskid(taskid);
        Audience audience = new Audience();
        audience.setAlias(aliasList);
        audienceDTO.setAudience(audience);
        audienceDTO.setAsync(async);
        ApiResult<Map<String, Map<String, String>>> result = pushApi.pushListByAlias(audienceDTO);
        if (!async) {
            if (result.isSuccess()) {
                log.info("推送成功");
                log.info("推送结果: {}", JSONUtil.toJsonStr(result.getData()));
            } else {
                log.error("推送失败: {}", JSONUtil.toJsonStr(result));
            }
        }
    }
}
